﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using NLog;

namespace sp2google.common
{
	static class SyncProviderHelper
	{
		public static Dictionary<string, SyncProviderInfo> LoadProviders(string rootPath)
		{
			Logger log = LogManager.GetLogger("common");
			Dictionary<string, SyncProviderInfo> syncProviderList = new Dictionary<string, SyncProviderInfo>();

			//The following only available on .Net 4.0, so I'm using an alternative, but not tested yet
			//IEnumerable<string> assemblyList = Directory.EnumerateFiles(rootPath, "SyncProvider*.dll");
			string[] assemblyList = Directory.GetFiles(rootPath, "SyncProvider*.dll");
			foreach (string assemblyPath in assemblyList)
			{
				log.Debug("Loading " + assemblyPath);
				try
				{
					Assembly asm = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
					//Loads the dependencies
					foreach (AssemblyName referencedAssembly in asm.GetReferencedAssemblies())
					{
						try
						{
							Assembly.ReflectionOnlyLoad(referencedAssembly.FullName);
						}
						catch
						{
							//Failsafe when default path cannot be found
							Assembly.ReflectionOnlyLoadFrom(Path.Combine(Path.GetDirectoryName(assemblyPath),
							                                             referencedAssembly.Name + ".dll"));
						}
					}

					Type exportedType = asm.GetType(Path.GetFileNameWithoutExtension(assemblyPath) + ".MainForm");
					if (exportedType != null)
					{
						log.Debug("\tChecking " + exportedType.FullName);
						//The following only available on .Net 4.0, so I'm using an alternative, but not tested yet
						//IList<CustomAttributeData> customAttributes = exportedType.GetCustomAttributesData();


						foreach (CustomAttributeData attributeData in customAttributes)
						{
							if (attributeData.Constructor.DeclaringType.FullName == "sp2google.common.SyncProviderBase")
							{
								if (attributeData.ConstructorArguments.Count == 2)
								{
									string syncProviderFileName = Path.GetFileNameWithoutExtension(assemblyPath);
									if (syncProviderFileName != null && !syncProviderList.ContainsKey(syncProviderFileName))
									{
										syncProviderList.Add(syncProviderFileName, new SyncProviderInfo()
										                                     	{
										                                     		ExecuteablePath = assemblyPath,
										                                     		FileName = syncProviderFileName
										                                     	});

									}
								}
							}
						}
					}
				}
				catch (BadImageFormatException)
				{
					//Catch for non .Net Assembly
				}
			}
			return syncProviderList;
		}
	}
}
